#include "xmlinterface.h"
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
#include <QMessageBox>
#include "xmlhandler.h"

XMLInterface::XMLInterface(QObject *parent) :
    QObject(parent)
{
    minimap = 0;
}

XMLInterface::~XMLInterface()
{
}

/**
  Create an xml file with prop info
  input:
    QString path - where to save the file
*/
bool XMLInterface::buildXML(QString path, bool keepLocalPaths)
{
    doc = new QDomDocument("propData");
    root = doc->createElement("props");
    doc->appendChild(root);

    if (keepLocalPaths)
    {
        QDomElement loc = doc->createElement("local");
        loc.appendChild(doc->createTextNode("1"));
        root.appendChild(loc);
    }

    // minimap
    if (minimap != NULL && minimap->pic.size() > 0)
    {
        QDomElement map = doc->createElement("minimap");
        QDomElement ptop = doc->createElement("point");
        QDomElement plow = doc->createElement("point");
        if (keepLocalPaths)
        {
            map.setAttribute("img", minimap->pic[0]->first);
        }
        else
        {
            map.setAttribute("img", translatePath(minimap->pic[0]->first, "Minimap"));
        }
        ptop.setAttribute("type", "topleft");
        plow.setAttribute("type", "lowright");
        QDomElement lattop = doc->createElement("lat");
        QDomElement lontop = doc->createElement("lon");
        QDomElement latlow = doc->createElement("lat");
        QDomElement lonlow = doc->createElement("lon");
        lattop.appendChild(doc->createTextNode(QString::number(minimap->propCoords[0].latitude, 'f', 6)));
        lontop.appendChild(doc->createTextNode(QString::number(minimap->propCoords[0].longitude, 'f', 6)));
        latlow.appendChild(doc->createTextNode(QString::number(minimap->propCoords[1].latitude, 'f', 6)));
        lonlow.appendChild(doc->createTextNode(QString::number(minimap->propCoords[1].longitude, 'f', 6)));
        ptop.appendChild(lattop);
        ptop.appendChild(lontop);
        plow.appendChild(latlow);
        plow.appendChild(lonlow);
        map.appendChild(ptop);
        map.appendChild(plow);
        root.appendChild(map);
    }
    /*else // TODO: may need this later
    {
        QMessageBox mbox;
        mbox.setText("You have not created any map data");
        mbox.setInformativeText("Do you really want to save (not recommended)?");
        QPushButton *save = mbox.addButton("Save", QMessageBox::AcceptRole);
        QPushButton *nope = mbox.addButton("Don't Save", QMessageBox::RejectRole);
        mbox.exec();
        if ((QPushButton *)mbox.clickedButton() == save)
        {
            // continue saving
        }
        else if ((QPushButton *)mbox.clickedButton() == nope)
        {
            return false;
        }
    }*/

    // props
    for (unsigned int k = 0; k < props.size(); k++)
    {
        QDomElement propElem = doc->createElement("prop");

        QDomElement propName = doc->createElement("propName");
        propName.appendChild(doc->createTextNode(props[k]->getPropName()));
        propElem.appendChild(propName);

        QDomElement propCoords = doc->createElement("coords");
        QDomElement point = doc->createElement("point");
        point.setAttribute("type", "center");
        QDomElement lat = doc->createElement("lat");
        QDomElement lon = doc->createElement("lon");
        QDomElement alt = doc->createElement("alt");
        QDomElement rad = doc->createElement("rad");
        lat.appendChild(doc->createTextNode(QString::number(props[k]->propCoords[0].latitude, 'f', 6)));
        lon.appendChild(doc->createTextNode(QString::number(props[k]->propCoords[0].longitude, 'f', 6)));
        alt.appendChild(doc->createTextNode(QString::number(props[k]->propCoords[0].altitude, 'f', 6)));
        rad.appendChild(doc->createTextNode(QString::number(props[k]->propCoords[0].radius, 'f', 6)));
        point.appendChild(lat);
        point.appendChild(lon);
        point.appendChild(alt);
        point.appendChild(rad);
        propCoords.appendChild(point);
        propElem.appendChild(propCoords);

        /*QDomElement audioMain = doc->createElement("audioMain");
        if (props[k]->getAudMain()->second == PROP_LOCAL_PATH)
        {
            if (props[k]->getAudMain()->first != "")
            {
                audioMain.appendChild(doc->createTextNode(translatePath(props[k]->getAudMain()->first,
                                                                        props[k]->getPropName())));
            }
            else
            {
                audioMain.appendChild(doc->createTextNode(""));
            }
        }
        else
        {
            audioMain.appendChild(doc->createTextNode(props[k]->getAudMain()->first));
        }
        if (props[k]->getAudMainScript()->second == PROP_LOCAL_PATH && props[k]->getAudMainScript()->first != "")
        {
            QFile audMainScript(QDir::tempPath() + "/" + props[k]->getPropName() + ".mainAud.txt");
            audMainScript.open(QFile::WriteOnly | QFile::Truncate);
            QTextStream scr(&audMainScript);
            scr << props[k]->audMainScript->first;
            audMainScript.close();
            props[k]->setAudMainScriptFile(audMainScript.fileName());
            audioMain.setAttribute("script", translatePath(audMainScript.fileName(),
                                                           props[k]->getPropName()));
        }
        else if (props[k]->getAudMainScript()->second == PROP_DEVICE_PATH)
        {
            audioMain.setAttribute("script", props[k]->getAudMainScriptFile()->first);
        }
        propElem.appendChild(audioMain);*/

        QDomElement media = doc->createElement("media");
        for (unsigned int j = 0; j < props[k]->aud.size(); j++)
        {
            QDomElement aud = doc->createElement("aud");
            if (!keepLocalPaths)
            {
                aud.appendChild(doc->createTextNode(translatePath(props[k]->aud[j]->first,
                                                                  props[k]->getPropName())));
            }
            else
            {
                aud.appendChild(doc->createTextNode(props[k]->aud[j]->first));
            }
            media.appendChild(aud);
        }
        for (unsigned int j = 0; j < props[k]->vid.size(); j++)
        {
            QDomElement vid = doc->createElement("vid");
            if (!keepLocalPaths)
            {
                vid.appendChild(doc->createTextNode(translatePath(props[k]->vid[j]->first,
                                                                  props[k]->getPropName())));
            }
            else
            {
                vid.appendChild(doc->createTextNode(props[k]->vid[j]->first));
            }
            media.appendChild(vid);
        }
        for (unsigned int j = 0; j < props[k]->pic.size(); j++)
        {
            QDomElement pic = doc->createElement("pic");
            if (!keepLocalPaths)
            {
                pic.appendChild(doc->createTextNode(translatePath(props[k]->pic[j]->first,
                                                                  props[k]->getPropName())));
            }
            else
            {
                pic.appendChild(doc->createTextNode(props[k]->pic[j]->first));
            }
            media.appendChild(pic);
        }
        propElem.appendChild(media);

        root.appendChild(propElem);
    }

    QString xml = doc->toString();
    qDebug() << xml;

    if (path != "")
    {
        QFile f(path);
        if (f.open(QFile::WriteOnly | QFile::Truncate))
        {
            QTextStream file(&f);
            file << xml;
            f.close();
        }
    }
    else
    {
    #ifdef Q_WS_WIN
        tmpXML = new QTemporaryFile(QDir::tempPath() + "\\artourXXXXXX.xml");
    #endif
    #ifndef Q_WS_WIN
        tmpXML = new QTemporaryFile("artourXXXXXX.xml");
    #endif
        if (tmpXML->open())
        {
            QTextStream file(tmpXML);
            file << xml;
            tmpXML->close();
        }
        qDebug() << tmpXML->fileName();
    }

    delete doc;
    return true;
}

QString XMLInterface::getTmpXmlFile()
{
    return tmpXML->fileName();
}

void XMLInterface::readXML(QString path)
{
    QXmlSimpleReader reader;
    QFile *f = new QFile(path);
    QXmlInputSource *src = new QXmlInputSource(f);
    XMLHandler *handler = new XMLHandler(this);

    reader.setContentHandler(handler);
    reader.setErrorHandler(handler);
    if (!reader.parse(src))
    {
        // TODO: possibly handler error
        qDebug() << "xml read error";
    }
}

void XMLInterface::addPropFromXML(PropData *prop)
{
    if (getPropByName(prop->getPropName()) != 0)
    {
        QMessageBox msgbox;
        msgbox.setText("Prop with name \"" + prop->getPropName() + "\" already exists on the device.");
        msgbox.setInformativeText("Would you like to use your prop or the device's prop?");
        QPushButton *xmlProp = msgbox.addButton("Device Prop", QMessageBox::AcceptRole);
        QPushButton *yourProp = msgbox.addButton("Your Prop", QMessageBox::RejectRole);
        msgbox.exec();
        if ((QPushButton *)msgbox.clickedButton() == xmlProp)
        {
            emit propRemoved(prop->getPropName());
            emit propAdded(prop, false);
        }
        else if ((QPushButton *)msgbox.clickedButton() == yourProp)
        {
            // do nothing
            delete prop;
            return;
        }
    }
    else
    {
        emit propAdded(prop, false);
    }
    /*if (prop->audMainScriptFile != "")
    {
        emit propAudioScriptRequest(prop);
    }*/
}

void XMLInterface::addProp(PropData *prop)
{
    props.push_back(prop);
}

PropData * XMLInterface::getPropByName(QString name)
{
    for (unsigned int k = 0; k < props.size(); k++)
    {
        if (props[k]->getPropName().toLower() == name.toLower())
            return props[k];
    }
    return 0;
}

void XMLInterface::removePropByName(QString name)
{
    for (unsigned int k = 0; k < props.size(); k++)
    {
        if (props[k]->getPropName().toLower() == name.toLower())
        {
            props.erase(props.begin()+k);
            return;
        }
    }
}

void XMLInterface::removeAllProps()
{
    for (unsigned int k = 0; k < props.size(); k++)
    {
        emit propRemovedXmlOnly(props[k]->getPropName());
    }
    if (minimap != 0)
    {
        emit propRemovedXmlOnly(minimap->getPropName());
        delete minimap;
        minimap = 0;
    }
    props.clear();
}

// call when a device is unplugged?
// maybe copy props from the device so they can be moved to others?
void XMLInterface::removeDeviceProps()
{
    /*unsigned int k = 0;
    while (props.size() > 0 && k < props.size())
    {
        if (props[k]->propLoc == PROP_IS_DEVICE)
        {
            props.erase(props.begin()+k);
        }
        else
        {
            k++;
        }
    }*/
}

std::vector<PropData *> XMLInterface::getAllProps()
{
    return props;
}

void XMLInterface::setMinimap(PropData *mmap)
{
    // force the use of clearMinimap() to delete minimap
    if (mmap != 0)
    {
        minimap = mmap;
    }
}

void XMLInterface::setMinimapFromXML(PropData *prop)
{
    /*if (minimap != NULL)
    {
        QMessageBox msgbox;
        msgbox.setText("Minimap data already exists on the device.");
        msgbox.setInformativeText("Would you like to use your map or the device's map?");
        QPushButton *xmlMap = msgbox.addButton("Device Map", QMessageBox::AcceptRole);
        QPushButton *yourMap = msgbox.addButton("Your Map", QMessageBox::RejectRole);
        msgbox.exec();
        if ((QPushButton *)msgbox.clickedButton() == xmlMap)
        {
            emit propRemoved("Minimap");
            emit minimapAdded(prop);
        }
        else if ((QPushButton *)msgbox.clickedButton() == yourMap)
        {
            // do nothing
            delete prop;
            return;
        }
    }
    else
    {*/
        emit minimapAdded(prop, false);
    //}
}

PropData * XMLInterface::getMinimap()
{
    return minimap;
}

void XMLInterface::clearMinimap()
{
    delete minimap;
    minimap = NULL;
}

/**
  Given a system path, generate a path that will be valid for the android device
  systemPath - Path to a file on this system.
  devicePathFolder - Folder in which the file will be placed. This is appended to DATAPATH.
    ex: if devicePathFolder is "Pictures", the folder on the device will be /DATAPATH/Pictures/
    By default, devicePathFolder is ""
  */
QString XMLInterface::translatePath(QString systemPath, QString devicePathFolder)
{
    QFileInfo file(systemPath);
    QString path = QString(DATAPATH) + devicePathFolder + "/" + file.fileName();
    return path;
}
